//----------------------------------------------------------------------------------------
// @Project Includes
#include "includes.h"

//----------------------------------------------------------------------------------------
// @Local Macro Define in the module

//----------------------------------------------------------------------------------------
// @Local Type defines in the module

//----------------------------------------------------------------------------------------
// @Global Variables define in the module
uint16_t  g_u16RegParm[COSM_REG_PARM_MAX_NUM] ={0};

//----------------------------------------------------------------------------------------
// @Prototypes of functions in the module
static void srv_cosm_printfData(uint8_t *buffer,uint16_t len);
static void srv_cosm_sendPacket(uint8_t *_buf, uint16_t _len);

static void srv_cosm_writeRegParmErrAck(uint16_t addr, uint16_t reglen);
static void srv_cosm_writeRegParmAck(uint16_t addr, uint16_t reglen);

static void srv_cosm_write(void);	
static void srv_cosm_analyze(void);
static void srv_cosm_poll(void);

//========================================================================================
static void srv_cosm_printfData(uint8_t *buffer,uint16_t len)
{
    uint16_t i = 0;
    if(len > 512)
    {
				printf("\r\n");
        return;
    }

    printf("\r\n");
    for(i = 0; i < len;i++)
    {
        printf("%02x ",buffer[i]);
    }
    printf("\r\n");
}

/**
 * @brief  cosm send packet
 * @param  buf: the data
 *         len:the data len
 * @return 
 * @note   
 */
static void srv_cosm_sendPacket(uint8_t *_buf, uint16_t _len)
{
		if (g_stcUart.stcSif1.brxCompleteFlg)
		{
//			RS485_SEND();
			drv_usart_sendData(USART_SIF1_INDEX, (void *)_buf, _len);
			printf("SIF1:<< TxLen = %d; TX:",_len);
			srv_cosm_printfData((void *)_buf, _len);		
		}	
		if (g_stcUart.stcSif2.brxCompleteFlg)
		{
//			RS485_SEND();
			drv_usart_sendData(USART_SIF2_INDEX, (void *)_buf, _len);
			printf("SIF2:<< TxLen = %d; TX:",_len);
			srv_cosm_printfData((void *)_buf, _len);		
		}		
		if (g_stcUart.stcRs485.brxCompleteFlg)
		{		
//			RS485_SEND();
			drv_usart_sendData(USART_RS485_INDEX, (void *)_buf, _len);
			printf("Modbus:<< TxLen = %d; TX:",_len);
			srv_cosm_printfData((void *)_buf, _len);	
		}
}
/**
 * @brief  write parm err ack
 * @param  
 * @return 
 * @note   
 */
static void srv_cosm_writeRegParmErrAck(uint16_t addr, uint16_t reglen)
{
    uint8_t u8TxBuf[COSM_TX_BUF_SIZE];
    uint16_t u16count = 0;
    uint8_t u8crc = 0;
		
    u16count = 0;
    u8TxBuf[u16count++] = COSM_PROTOCOL_HEAD;
		u8TxBuf[u16count++] = COSM_PROTOCOL_ADDRESS;
    u8TxBuf[u16count++] = COSM_PROTOCOL_WRITE;
    u8TxBuf[u16count++] = COSM_WRITE_STATE_ADDRESS_ERROR;
	
    u8crc = srv_crc8_cosm(&u8TxBuf[1], u16count-1);
		u8TxBuf[u16count++] = u8crc;
    u8TxBuf[u16count++] = COSM_PROTOCOL_TAIL;
		srv_cosm_sendPacket(u8TxBuf, u16count);
		
}

/**
 * @brief  write ota info ack
 * @param  
 * @return 
 * @note   
 */
void srv_cosm_writeOtaInfoAck(void)
{
    uint8_t u8TxBuf[COSM_TX_BUF_SIZE];
    uint16_t u16count = 0;
		//uint16_t u16i = 0;
    uint8_t u8crc = 0;

    u16count = 0;
    u8TxBuf[u16count++] = COSM_PROTOCOL_HEAD;
		u8TxBuf[u16count++] = COSM_PROTOCOL_ADDRESS;
    u8TxBuf[u16count++] = COSM_PROTOCOL_WRITE;
    u8TxBuf[u16count++] = COSM_WRITE_STATE_SUCCESS;
	
    u8crc = srv_crc8_cosm(&u8TxBuf[1], u16count-1);
		u8TxBuf[u16count++] = u8crc;
    u8TxBuf[u16count++] = COSM_PROTOCOL_TAIL;
		g_stcUart.stcRs485.brxCompleteFlg = true;
		srv_cosm_sendPacket(u8TxBuf, u16count);
		g_stcUart.stcRs485.brxCompleteFlg = false;
	
		g_stcUart.stcSif1.brxCompleteFlg = true;
		srv_cosm_sendPacket(u8TxBuf, u16count);
		g_stcUart.stcSif1.brxCompleteFlg = false;
	
		g_stcUart.stcSif2.brxCompleteFlg = true;
		srv_cosm_sendPacket(u8TxBuf, u16count);
		g_stcUart.stcSif2.brxCompleteFlg = false;	
}


/**
 * @brief  write parm ack
 * @param  
 * @return 
 * @note   
 */
static void srv_cosm_writeRegParmAck(uint16_t addr, uint16_t reglen)
{
		uint8_t Temp[USART_RS485_MAX_RX_SIZE] = {0};
		
    uint8_t writeBuf[UPDATE_TAG_SIZE] = {0};
    uint8_t readBuf[UPDATE_TAG_SIZE] = {0};
		
    uint8_t u8TxBuf[COSM_TX_BUF_SIZE];
    uint16_t u16count = 0;
		//uint16_t u16i = 0;
    uint8_t u8crc = 0;
	  //uint16_t u16ctlcmd = 0;
    uint16_t i = 0;	
	
    u16count = 0;
    u8TxBuf[u16count++] = COSM_PROTOCOL_HEAD;
		u8TxBuf[u16count++] = COSM_PROTOCOL_ADDRESS;
    u8TxBuf[u16count++] = COSM_PROTOCOL_WRITE;
    u8TxBuf[u16count++] = COSM_WRITE_STATE_SUCCESS;
	
		if (addr == COSM_OTA_INFO_ADDR)
		{
				writeBuf[0] = 0x5A;
				writeBuf[1] = 0xA5;
				memcpy(&writeBuf[2],&g_stcUart.stcRs485.u8rxBackbuff[7],9); 
			
				drv_flash_write(writeBuf, OTA_CONFIG_ADDR, UPDATE_TAG_SIZE);
				drv_flash_read(readBuf, OTA_CONFIG_ADDR, UPDATE_TAG_SIZE);
				for (i = 0; i < UPDATE_TAG_SIZE; i++)
				{
						if (writeBuf[i] != readBuf[i])
						{
								printf("Modbus:<< OTA write update data error!g_stcVar.m_stcUpgInfo[%d]=0x%0x tempBuf[%d]=0x%0x\r\n", i, writeBuf[i], i, readBuf[i]);
								memset((void *) writeBuf, 0x00, 11);
								drv_flash_write(writeBuf, OTA_CONFIG_ADDR, UPDATE_TAG_SIZE);
								return ; 
						}
				}
				
				gstcOtaUpdata.flag = (((uint16_t)readBuf[0] << 8)|((uint16_t)readBuf[1]));
				gstcOtaUpdata.ecu =  readBuf[2];
				gstcOtaUpdata.u16fwVer = (((uint16_t)readBuf[3] << 8)|((uint16_t)readBuf[4]));
				gstcOtaUpdata.u32fwSize = (((uint32_t)readBuf[5]<<24) | ((uint32_t)readBuf[6] << 16) | ((uint32_t)readBuf[7] << 8) | ((uint32_t)readBuf[8]));
				gstcOtaUpdata.u16fwCrc16 = (((uint16_t)readBuf[9] << 8)|((uint16_t)readBuf[10]));
				
//				printf("Modbus:<< goto boot upgrade, restart and enter BOOT....\r\n ");
//				drv_systick_delay_ms(2);
//				NVIC_SystemReset();
		}
		else if (addr == COSM_OTA_UPDATA_ADDR)
		{
        gstcOtaUpdataInfo.ecu =  g_stcUart.stcRs485.u8rxBackbuff[7];
        gstcOtaUpdataInfo.u16fwVer = (((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[8] << 8) | ((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[9]));
        gstcOtaUpdataInfo.offset = (((uint32_t)g_stcUart.stcRs485.u8rxBackbuff[10]<<24) | ((uint32_t)g_stcUart.stcRs485.u8rxBackbuff[11]<< 16) | ((uint32_t)g_stcUart.stcRs485.u8rxBackbuff[12]<< 8) | ((uint32_t)g_stcUart.stcRs485.u8rxBackbuff[13]));
        gstcOtaUpdataInfo.len = (((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[14] << 8) | ((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[15]));
        printf("Modbus:<<  mobus receive upgradedata  pre ecu= 0x%x ,ver= %d  offset = %d   datalen  = %d  \r\n", gstcOtaUpdataInfo.ecu,gstcOtaUpdataInfo.u16fwVer,gstcOtaUpdataInfo.offset,gstcOtaUpdataInfo.len);
        if((gstcOtaUpdataInfo.ecu == gstcOtaUpdata.ecu)&&(gstcOtaUpdataInfo.u16fwVer == gstcOtaUpdata.u16fwVer)&&(gstcOtaUpdataInfo.len <= USART_RS485_MAX_RX_SIZE))
        {
            if(gstcOtaUpdataInfo.offset == 0)/*???*/
            {		
                gstcOtaUpdataInfo.u16fwCrc16 = 0;
                drv_flash_write(&g_stcUart.stcRs485.u8rxBackbuff[16], DEVICE_MAIN_APP_ADDR + gstcOtaUpdataInfo.offset, gstcOtaUpdataInfo.len);
                drv_flash_read(Temp, DEVICE_MAIN_APP_ADDR+ gstcOtaUpdataInfo.offset, gstcOtaUpdataInfo.len);
                gstcOtaUpdataInfo.u16fwCrc16 = srv_crc16_system(Temp,gstcOtaUpdataInfo.len,gstcOtaUpdataInfo.u16fwCrc16);
                printf("Modbus:<<  receive upgradedata   ***gstcOtaUpdataInfo.u16fwCrc16 = 0x%x  ****\r\n",gstcOtaUpdataInfo.u16fwCrc16);
            }
            else if((gstcOtaUpdataInfo.offset+gstcOtaUpdataInfo.len) == gstcOtaUpdata.u32fwSize)/*??????*/
            {
                drv_flash_write(&g_stcUart.stcRs485.u8rxBackbuff[16], DEVICE_MAIN_APP_ADDR + gstcOtaUpdataInfo.offset, gstcOtaUpdataInfo.len);
                drv_flash_read(Temp, DEVICE_MAIN_APP_ADDR+ gstcOtaUpdataInfo.offset, gstcOtaUpdataInfo.len);
                gstcOtaUpdataInfo.u16fwCrc16 = srv_crc16_system(Temp,gstcOtaUpdataInfo.len,gstcOtaUpdataInfo.u16fwCrc16);
                printf("Modbus:<<  receive upgradedata   ***gstcOtaUpdataInfo.u16fwCrc16 = 0x%x  ****\r\n",gstcOtaUpdataInfo.u16fwCrc16);
				
                if(gstcOtaUpdataInfo.u16fwCrc16  == gstcOtaUpdata.u16fwCrc16)/*????*/
                {			
                    /*????*/
                    gstcOtaUpdataInfo.progress = 100;
                    printf("Modbus:<<  upgrade success goto bootloader \r\n");
                }
                else
                {
                    /*????*/
                    gstcOtaUpdataInfo.progress = 0;
                    printf("Modbus:<<  upgrade save info fail  crc error \r\n");
                }
            }
            else
            {
                drv_flash_write(&g_stcUart.stcRs485.u8rxBackbuff[16], DEVICE_MAIN_APP_ADDR + gstcOtaUpdataInfo.offset, gstcOtaUpdataInfo.len);
                drv_flash_read(Temp, DEVICE_MAIN_APP_ADDR+ gstcOtaUpdataInfo.offset, gstcOtaUpdataInfo.len);
                gstcOtaUpdataInfo.u16fwCrc16 = srv_crc16_system(Temp,gstcOtaUpdataInfo.len,gstcOtaUpdataInfo.u16fwCrc16);
                printf("Modbus:<<  receive upgradedata   ***m_stcUpg.u16fwCrc16 = 0x%x  ****\r\n",gstcOtaUpdataInfo.u16fwCrc16);
            }
            //g_stcSysVar.m_OtaTimeOut = OTA_TIMEOUT_VLUE;		
        }			
		}
		else if (addr == COSM_OTA_RESULT_ADDR)
		{
				#define MAGIC_ADDR_BASE   (0x8005000)
				#define MAGIC_REVISION   ("CBMS-xxx-0328800387")
				uint8_t cRevision_Magic[40] = {0};
			
				drv_flash_read(cRevision_Magic, MAGIC_ADDR_BASE, sizeof(MAGIC_REVISION));	

				if (strcmp((char*)cRevision_Magic, MAGIC_REVISION) == 0)
				{   
						printf("magic check ok!\r\n");
				}
				else
				{
						gstcOtaUpdataInfo.progress = 0;
						printf("magic check error!\r\n");
				}
				
				if(gstcOtaUpdataInfo.progress == 100)
				{
						u8TxBuf[3] = COSM_WRITE_STATE_SUCCESS;
				}
				else
				{
						u8TxBuf[3] = COSM_WRITE_STATE_OPT_ERROR;
				}
				
				u8crc = srv_crc8_cosm(&u8TxBuf[1], u16count-1);
				u8TxBuf[u16count++] = u8crc;
				u8TxBuf[u16count++] = COSM_PROTOCOL_TAIL;
				srv_cosm_sendPacket(u8TxBuf, u16count);
				
				if (gstcOtaUpdataInfo.progress == 100)
				{
						memset((void *) writeBuf, 0x00, 11);
						drv_flash_write(writeBuf, OTA_CONFIG_ADDR, UPDATE_TAG_SIZE);
						printf("Modbus:<< The upgrade is complete, restart and enter BOOT....\r\n ");

						NVIC_SystemReset();			
				}
				else
				{
						return ;
				}			
		}
		else
		{
//			for (u16i = 0; u16i < reglen; u16i++)
//			{
//					g_u16RegParm[addr + u16i] = (((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[7+2*u16i] << 8) | ((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[8+2*u16i]));
//			}

//			g_stcVar.bparmWriteFlag = true;
//			g_stcVar.u16parmWriteWaitTime = PARM_WRITE_MAX_WAIT_TIME;			
		}
		
    u8crc = srv_crc8_cosm(&u8TxBuf[1], u16count-1);
		u8TxBuf[u16count++] = u8crc;
    u8TxBuf[u16count++] = COSM_PROTOCOL_TAIL;
		srv_cosm_sendPacket(u8TxBuf, u16count);
		
}

/**
 * @brief  cosm write
 * @param  
 * @return 
 * @note   
 */ 
static void srv_cosm_write(void)
{
		uint16_t u16regStartAddr = 0;	
		uint16_t u16regLen = 0;	
	
		u16regStartAddr = (((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[3] << 8) | ((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[4]));
		u16regLen = (((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[5] << 8) | ((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[6]));

		if (u16regStartAddr == COSM_OTA_INFO_ADDR)
		{
			  if (u16regLen != 9 )
        {
					  srv_cosm_writeRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						printf("Modbus:<<  ota info init \r\n");
						memset(&gstcOtaUpdata,0x0,sizeof(stc_ota_updata_t));
						memset(&gstcOtaUpdataInfo,0x0,sizeof(stc_ota_updatainfo_t));
					
						srv_cosm_writeRegParmAck(u16regStartAddr, u16regLen);
				}			
		}	
		else if (u16regStartAddr == COSM_OTA_UPDATA_ADDR)
		{
				srv_cosm_writeRegParmAck(u16regStartAddr, u16regLen);
		}	
		else if (u16regStartAddr == COSM_OTA_RESULT_ADDR)
		{
				srv_cosm_writeRegParmAck(u16regStartAddr, u16regLen);
		}		
		else
		{
			srv_cosm_writeRegParmErrAck(u16regStartAddr, u16regLen);
		}	
}

/**
 * @brief  cosm data analyze app
 * @param  
 * @return 
 * @note   
 */
static void srv_cosm_analyze(void)
{	
		if (g_stcUart.stcRs485.u8rxBackbuff[2] == COSM_PROTOCOL_WRITE)
		{
			  srv_cosm_write();
		}
		else
		{
				// todo
		}
}

/**
 * @brief  cosm data poll
 * @param  
 * @return 
 * @note   
 */
static void srv_cosm_poll(void)
{
    uint8_t crc1 = 0;
		uint8_t u8temp = 0;
		
    if (g_stcUart.stcRs485.vu32rxBackMQPush < 9)
    {
			  printf("Modbus:<< the size error  crc1=%d RxCount = %d; RX:",crc1,g_stcUart.stcRs485.vu32rxBackMQPush);
				srv_cosm_printfData(g_stcUart.stcRs485.u8rxBackbuff, g_stcUart.stcRs485.vu32rxBackMQPush);
        g_stcUart.stcRs485.vu32rxBackMQPush = 0;	
        return;
    }
		
		if ((g_stcUart.stcRs485.u8rxBackbuff[0]!= COSM_PROTOCOL_HEAD)||
			  (g_stcUart.stcRs485.u8rxBackbuff[g_stcUart.stcRs485.vu32rxBackMQPush-1]!= COSM_PROTOCOL_TAIL)
		)
		{
				printf("Modbus:<< the head and tail error  crc1=%d RxCount = %d; RX:",crc1,g_stcUart.stcRs485.vu32rxBackMQPush);
				srv_cosm_printfData(g_stcUart.stcRs485.u8rxBackbuff, g_stcUart.stcRs485.vu32rxBackMQPush);
        g_stcUart.stcRs485.vu32rxBackMQPush = 0;	
        return;			
		}
		
    if (g_stcUart.stcRs485.u8rxBackbuff[1] != COSM_PROTOCOL_ADDRESS)
    {
				printf("Modbus:<< the address error  crc1=%d RxCount = %d; RX:",crc1,g_stcUart.stcRs485.vu32rxBackMQPush);
				srv_cosm_printfData(g_stcUart.stcRs485.u8rxBackbuff, g_stcUart.stcRs485.vu32rxBackMQPush);			
        g_stcUart.stcRs485.vu32rxBackMQPush = 0;	
        return;
    }		
		
    crc1 = srv_crc8_cosm(&g_stcUart.stcRs485.u8rxBackbuff[1], g_stcUart.stcRs485.vu32rxBackMQPush - 3);
		u8temp = g_stcUart.stcRs485.u8rxBackbuff[g_stcUart.stcRs485.vu32rxBackMQPush - 2];
		
    if (crc1 != u8temp)
    {
				printf("Modbus:<< the CRC error  crc1=%d RxCount = %d; RX:",crc1,g_stcUart.stcRs485.vu32rxBackMQPush);
				srv_cosm_printfData(g_stcUart.stcRs485.u8rxBackbuff, g_stcUart.stcRs485.vu32rxBackMQPush);
		}	
		else
		{	
				printf("Modbus:<< the Modbus data format is correct, RxCount = %d; RX:",g_stcUart.stcRs485.vu32rxBackMQPush);
				srv_cosm_printfData(g_stcUart.stcRs485.u8rxBackbuff, g_stcUart.stcRs485.vu32rxBackMQPush);
				srv_cosm_analyze();
		}
    	
		g_stcUart.stcRs485.vu32rxBackMQPush = 0;

}

/**
 * @brief  cosm receive process
 * @param  
 * @return 
 * @note   
 */
void srv_cosm_receiveProcess(void)
{
    if (g_stcUart.stcRs485.brxCompleteFlg)		
    {
//        srv_cosm_poll();
//				g_stcUart.stcRs485.brxCompleteFlg = false;
			
				memcpy(&g_stcUart.stcRs485.u8rxBackbuff[0] ,&g_stcUart.stcRs485.u8rxbuff[0],g_stcUart.stcRs485.vu32rxMQPush);
				g_stcUart.stcRs485.vu32rxBackMQPush = g_stcUart.stcRs485.vu32rxMQPush;			
        srv_cosm_poll();
				g_stcUart.stcRs485.brxCompleteFlg = false;
				g_stcUart.stcRs485.vu32rxMQPush = 0;				
			
    }	
		
    if (g_stcUart.stcSif1.brxCompleteFlg)		
    {
				memcpy(&g_stcUart.stcRs485.u8rxBackbuff[0] ,&g_stcUart.stcSif1.u8rxbuff[0],g_stcUart.stcSif1.vu32rxMQPush);
				g_stcUart.stcRs485.vu32rxBackMQPush = g_stcUart.stcSif1.vu32rxMQPush;			
        srv_cosm_poll();
				g_stcUart.stcSif1.brxCompleteFlg = false;
				g_stcUart.stcSif1.vu32rxMQPush = 0;	
    }	
    if (g_stcUart.stcSif2.brxCompleteFlg)		
    {
				memcpy(&g_stcUart.stcRs485.u8rxBackbuff[0] ,&g_stcUart.stcSif2.u8rxbuff[0],g_stcUart.stcSif2.vu32rxMQPush);
				g_stcUart.stcRs485.vu32rxBackMQPush = g_stcUart.stcSif2.vu32rxMQPush;			
        srv_cosm_poll();
				g_stcUart.stcSif2.brxCompleteFlg = false;
				g_stcUart.stcSif2.vu32rxMQPush = 0;	
    }			
}

// =======================================================================================
// End of file.
// =======================================================================================
